package com.audaque.springboot.foshanupload.mongodb.component;

/**
 * @author zgb
 * @desc ...
 * @date 2023-08-15 18:30:49
 */

import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener;
import org.springframework.data.mongodb.core.mapping.event.BeforeConvertEvent;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.lang.reflect.Field;
import java.util.List;

/**
 * mongoDB实现级联存储,支持List列表级联存储
 */
@Component
public class CascadingMongoEventListener extends AbstractMongoEventListener {

    @Resource
    private MongoOperations mongoOperations;

    @Override
    public void onBeforeConvert(BeforeConvertEvent event) {
        Object document = event.getSource();
        ReflectionUtils.doWithFields(document.getClass(), new CascadeCallback(document, mongoOperations));
    }
    private static class CascadeCallback implements ReflectionUtils.FieldCallback {
        private final Object source;
        private final MongoOperations mongoOperations;
        public CascadeCallback(Object source, MongoOperations mongoOperations) {
            this.source = source;
            this.mongoOperations = mongoOperations;
        }
        @Override
        public void doWith(@NotNull Field field) throws IllegalArgumentException, IllegalAccessException {
            ReflectionUtils.makeAccessible(field);
            if (!field.isAnnotationPresent(DBRef.class)) {
                return;
            }
            Object fieldValue = field.get(source);
            if(fieldValue == null) {
                return;
            }
            //实现从里到外保存
            if(fieldValue instanceof List) {
                List<?> list = (List<?>) fieldValue;
                if(list!=null&&!list.isEmpty()){
                    list.forEach(mongoOperations::save);
                }
            } else {
                if(fieldValue!=null){
                    mongoOperations.save(fieldValue);
                }
            }
        }
    }
}
